#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
基于Tkinter的汽车仪表盘图形界面
确保在任何Windows系统上都能运行，支持编译为exe

功能特性：
- 使用Python内置的tkinter库
- 真实的GUI界面
- 实时数据更新
- 可编译为独立exe文件
- 无需额外依赖
"""

import tkinter as tk
from tkinter import ttk, Canvas
import time
import threading
import random
import math
import sys
from dataclasses import dataclass

@dataclass
class Config:
    """配置类"""
    WINDOW_WIDTH: int = 900
    WINDOW_HEIGHT: int = 700
    MAX_SPEED: int = 220
    MAX_RPM: int = 8000
    UPDATE_INTERVAL: float = 0.05  # 50ms
    BG_COLOR: str = '#0f0f23'
    PANEL_COLOR: str = '#1a1a3a'
    ACCENT_COLOR: str = '#00ff41'

config = Config()

class VehicleData:
    """车辆数据模型"""
    def __init__(self):
        self.current_speed = 0
        self.target_speed = 60
        self.current_rpm = 800
        self.current_gear = 1
        self.fuel_level = 85.0
        self.engine_temp = 90.0
        self.odometer = 123456
        self.is_running = True
        self.trip_distance = 0.0
        
    def update(self):
        """更新车辆数据"""
        # 平滑速度变化
        if self.current_speed < self.target_speed:
            self.current_speed = min(self.current_speed + 1.5, self.target_speed)
        elif self.current_speed > self.target_speed:
            self.current_speed = max(self.current_speed - 2.0, self.target_speed)
        
        # 计算转速
        if self.current_speed == 0:
            self.current_rpm = 800  # 怠速
        else:
            self.current_rpm = 800 + (self.current_speed * 28)
            if self.current_rpm > config.MAX_RPM:
                self.current_rpm = config.MAX_RPM
        
        # 计算档位
        if self.current_speed == 0:
            self.current_gear = 0  # P档
        elif self.current_speed < 25:
            self.current_gear = 1
        elif self.current_speed < 45:
            self.current_gear = 2
        elif self.current_speed < 70:
            self.current_gear = 3
        elif self.current_speed < 100:
            self.current_gear = 4
        else:
            self.current_gear = 5
        
        # 模拟燃油消耗
        if self.current_speed > 0:
            consumption_rate = 0.002 + (self.current_speed * 0.00001)
            self.fuel_level = max(0, self.fuel_level - consumption_rate)
            
            # 更新行驶里程
            self.trip_distance += self.current_speed * (config.UPDATE_INTERVAL / 3600)
        
        # 模拟引擎温度
        target_temp = 85 + (self.current_speed * 0.2)
        if self.engine_temp < target_temp:
            self.engine_temp = min(self.engine_temp + 0.1, target_temp)
        elif self.engine_temp > target_temp:
            self.engine_temp = max(self.engine_temp - 0.1, target_temp)

class CircularGauge:
    """圆形仪表盘组件"""
    
    def __init__(self, canvas, x, y, radius, min_val, max_val, title, unit, color):
        self.canvas = canvas
        self.x = x
        self.y = y
        self.radius = radius
        self.min_val = min_val
        self.max_val = max_val
        self.title = title
        self.unit = unit
        self.color = color
        self.value = min_val
        
        self.create_gauge()
    
    def create_gauge(self):
        """创建仪表盘"""
        # 外圆
        self.canvas.create_oval(
            self.x - self.radius, self.y - self.radius,
            self.x + self.radius, self.y + self.radius,
            outline='#444444', width=3, fill=config.PANEL_COLOR
        )
        
        # 内圆
        inner_radius = self.radius - 15
        self.canvas.create_oval(
            self.x - inner_radius, self.y - inner_radius,
            self.x + inner_radius, self.y + inner_radius,
            outline='#666666', width=2, fill=config.BG_COLOR
        )
        
        # 刻度
        self.draw_scale()
        
        # 标题
        self.canvas.create_text(
            self.x, self.y - 30,
            text=self.title,
            fill='white',
            font=('Arial', 12, 'bold')
        )
        
        # 数值显示
        self.value_text = self.canvas.create_text(
            self.x, self.y + 20,
            text=f"{self.value:.0f}",
            fill=self.color,
            font=('Arial', 24, 'bold')
        )
        
        # 单位
        self.canvas.create_text(
            self.x, self.y + 40,
            text=self.unit,
            fill='#888888',
            font=('Arial', 10)
        )
        
        # 指针
        self.needle = None
        self.update_needle()
    
    def draw_scale(self):
        """绘制刻度"""
        scale_radius = self.radius - 25
        for i in range(0, 11):  # 11个刻度
            angle = math.radians(225 - (270 * i / 10))  # 从225°到-45°
            
            # 主刻度
            x1 = self.x + (scale_radius - 10) * math.cos(angle)
            y1 = self.y + (scale_radius - 10) * math.sin(angle)
            x2 = self.x + scale_radius * math.cos(angle)
            y2 = self.y + scale_radius * math.sin(angle)
            
            self.canvas.create_line(x1, y1, x2, y2, fill='#666666', width=2)
            
            # 刻度数值
            if i % 2 == 0:  # 只显示偶数刻度的数值
                value = self.min_val + (self.max_val - self.min_val) * i / 10
                text_x = self.x + (scale_radius - 20) * math.cos(angle)
                text_y = self.y + (scale_radius - 20) * math.sin(angle)
                self.canvas.create_text(
                    text_x, text_y,
                    text=f"{value:.0f}",
                    fill='#888888',
                    font=('Arial', 8)
                )
    
    def update_needle(self):
        """更新指针"""
        if self.needle:
            self.canvas.delete(self.needle)
        
        # 计算指针角度
        ratio = (self.value - self.min_val) / (self.max_val - self.min_val)
        angle = math.radians(225 - 270 * ratio)
        
        # 指针长度
        needle_length = self.radius - 30
        
        # 指针坐标
        needle_x = self.x + needle_length * math.cos(angle)
        needle_y = self.y + needle_length * math.sin(angle)
        
        # 绘制指针
        self.needle = self.canvas.create_line(
            self.x, self.y, needle_x, needle_y,
            fill=self.color, width=4, capstyle='round'
        )
        
        # 中心圆
        self.canvas.create_oval(
            self.x - 8, self.y - 8, self.x + 8, self.y + 8,
            fill=self.color, outline=self.color
        )
    
    def set_value(self, value):
        """设置数值"""
        self.value = max(self.min_val, min(self.max_val, value))
        self.update_needle()
        
        # 更新数值显示
        self.canvas.itemconfig(self.value_text, text=f"{self.value:.0f}")

class Dashboard:
    """仪表盘主类"""
    
    def __init__(self):
        self.vehicle = VehicleData()
        self.root = None
        self.canvas = None
        self.speed_gauge = None
        self.rpm_gauge = None
        
        self.create_window()
        self.create_widgets()
        self.start_update_thread()
    
    def create_window(self):
        """创建主窗口"""
        self.root = tk.Tk()
        self.root.title("🚗 Python汽车仪表盘 - Tkinter版")
        self.root.geometry(f"{config.WINDOW_WIDTH}x{config.WINDOW_HEIGHT}")
        self.root.resizable(False, False)
        self.root.configure(bg=config.BG_COLOR)
        
        # 设置窗口图标（如果有的话）
        try:
            # self.root.iconbitmap('icon.ico')
            pass
        except:
            pass
        
        # 居中显示
        self.center_window()
    
    def center_window(self):
        """窗口居中"""
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        
        x = (screen_width - config.WINDOW_WIDTH) // 2
        y = (screen_height - config.WINDOW_HEIGHT) // 2
        
        self.root.geometry(f"{config.WINDOW_WIDTH}x{config.WINDOW_HEIGHT}+{x}+{y}")
    
    def create_widgets(self):
        """创建界面组件"""
        # 标题
        title_frame = tk.Frame(self.root, bg=config.BG_COLOR)
        title_frame.pack(pady=20)
        
        title_label = tk.Label(
            title_frame,
            text="🚗 Python + Tkinter 汽车仪表盘",
            font=('Arial', 20, 'bold'),
            bg=config.BG_COLOR,
            fg='white'
        )
        title_label.pack()
        
        # 主画布
        self.canvas = Canvas(
            self.root,
            width=config.WINDOW_WIDTH - 40,
            height=400,
            bg=config.BG_COLOR,
            highlightthickness=0
        )
        self.canvas.pack(pady=10)
        
        # 创建仪表盘
        self.create_gauges()
        
        # 信息面板
        self.create_info_panel()
        
        # 控制按钮
        self.create_control_panel()
    
    def create_gauges(self):
        """创建仪表盘"""
        # 速度表
        self.speed_gauge = CircularGauge(
            self.canvas, 200, 200, 120,
            0, config.MAX_SPEED,
            "车速", "km/h", config.ACCENT_COLOR
        )
        
        # 转速表
        self.rpm_gauge = CircularGauge(
            self.canvas, 500, 200, 100,
            0, config.MAX_RPM,
            "转速", "RPM", "#ff8800"
        )
        
        # 档位显示
        self.create_gear_display()
    
    def create_gear_display(self):
        """创建档位显示"""
        gear_x, gear_y = 700, 200
        
        # 档位背景
        self.canvas.create_rectangle(
            gear_x - 50, gear_y - 50,
            gear_x + 50, gear_y + 50,
            outline='#444444', width=2,
            fill=config.PANEL_COLOR
        )
        
        # 档位标题
        self.canvas.create_text(
            gear_x, gear_y - 30,
            text="档位",
            fill='white',
            font=('Arial', 12, 'bold')
        )
        
        # 档位数值
        self.gear_text = self.canvas.create_text(
            gear_x, gear_y,
            text="P",
            fill=config.ACCENT_COLOR,
            font=('Arial', 36, 'bold')
        )
    
    def create_info_panel(self):
        """创建信息面板"""
        info_frame = tk.Frame(self.root, bg=config.PANEL_COLOR)
        info_frame.pack(fill='x', padx=20, pady=10)
        
        # 燃油信息
        fuel_frame = tk.Frame(info_frame, bg=config.PANEL_COLOR)
        fuel_frame.pack(side='left', padx=20, pady=10)
        
        tk.Label(fuel_frame, text="燃油", bg=config.PANEL_COLOR, fg='white', font=('Arial', 12)).pack()
        self.fuel_progress = ttk.Progressbar(
            fuel_frame, length=150, mode='determinate',
            maximum=100, value=85
        )
        self.fuel_progress.pack(pady=5)
        self.fuel_label = tk.Label(fuel_frame, text="85.0%", bg=config.PANEL_COLOR, fg=config.ACCENT_COLOR)
        self.fuel_label.pack()
        
        # 温度信息
        temp_frame = tk.Frame(info_frame, bg=config.PANEL_COLOR)
        temp_frame.pack(side='left', padx=20, pady=10)
        
        tk.Label(temp_frame, text="水温", bg=config.PANEL_COLOR, fg='white', font=('Arial', 12)).pack()
        self.temp_progress = ttk.Progressbar(
            temp_frame, length=150, mode='determinate',
            maximum=120, value=90
        )
        self.temp_progress.pack(pady=5)
        self.temp_label = tk.Label(temp_frame, text="90°C", bg=config.PANEL_COLOR, fg='#ff8800')
        self.temp_label.pack()
        
        # 里程信息
        trip_frame = tk.Frame(info_frame, bg=config.PANEL_COLOR)
        trip_frame.pack(side='right', padx=20, pady=10)
        
        tk.Label(trip_frame, text="行驶信息", bg=config.PANEL_COLOR, fg='white', font=('Arial', 12)).pack()
        self.odometer_label = tk.Label(
            trip_frame, text="总里程: 123456 km",
            bg=config.PANEL_COLOR, fg='white'
        )
        self.odometer_label.pack()
        self.trip_label = tk.Label(
            trip_frame, text="本次: 0.0 km",
            bg=config.PANEL_COLOR, fg='white'
        )
        self.trip_label.pack()
    
    def create_control_panel(self):
        """创建控制面板"""
        control_frame = tk.Frame(self.root, bg=config.BG_COLOR)
        control_frame.pack(pady=20)
        
        # 速度控制
        tk.Button(
            control_frame, text="加速 (+20)",
            command=self.accelerate,
            bg=config.ACCENT_COLOR, fg='black',
            font=('Arial', 12, 'bold'),
            width=12
        ).pack(side='left', padx=10)
        
        tk.Button(
            control_frame, text="减速 (-20)",
            command=self.decelerate,
            bg='#ff4444', fg='white',
            font=('Arial', 12, 'bold'),
            width=12
        ).pack(side='left', padx=10)
        
        tk.Button(
            control_frame, text="随机速度",
            command=self.random_speed,
            bg='#4488ff', fg='white',
            font=('Arial', 12, 'bold'),
            width=12
        ).pack(side='left', padx=10)
        
        tk.Button(
            control_frame, text="停车",
            command=self.stop_vehicle,
            bg='#ff8800', fg='white',
            font=('Arial', 12, 'bold'),
            width=12
        ).pack(side='left', padx=10)
        
        # 状态显示
        self.status_label = tk.Label(
            self.root,
            text="状态: 启动中...",
            bg=config.BG_COLOR, fg='white',
            font=('Arial', 12)
        )
        self.status_label.pack(pady=10)
    
    def accelerate(self):
        """加速"""
        self.vehicle.target_speed = min(config.MAX_SPEED, self.vehicle.target_speed + 20)
    
    def decelerate(self):
        """减速"""
        self.vehicle.target_speed = max(0, self.vehicle.target_speed - 20)
    
    def random_speed(self):
        """随机速度"""
        self.vehicle.target_speed = random.randint(0, config.MAX_SPEED)
    
    def stop_vehicle(self):
        """停车"""
        self.vehicle.target_speed = 0
    
    def update_display(self):
        """更新显示"""
        # 更新仪表盘
        self.speed_gauge.set_value(self.vehicle.current_speed)
        self.rpm_gauge.set_value(self.vehicle.current_rpm)
        
        # 更新档位
        if self.vehicle.current_gear == 0:
            gear_text = "P"
            gear_color = '#ff4444'
        else:
            gear_text = str(self.vehicle.current_gear)
            gear_color = config.ACCENT_COLOR
        
        self.canvas.itemconfig(self.gear_text, text=gear_text, fill=gear_color)
        
        # 更新燃油
        self.fuel_progress['value'] = self.vehicle.fuel_level
        fuel_color = config.ACCENT_COLOR if self.vehicle.fuel_level > 20 else '#ff4444'
        self.fuel_label.config(text=f"{self.vehicle.fuel_level:.1f}%", fg=fuel_color)
        
        # 更新温度
        self.temp_progress['value'] = self.vehicle.engine_temp
        temp_color = '#ff8800' if self.vehicle.engine_temp < 100 else '#ff4444'
        self.temp_label.config(text=f"{self.vehicle.engine_temp:.0f}°C", fg=temp_color)
        
        # 更新里程
        self.odometer_label.config(text=f"总里程: {self.vehicle.odometer} km")
        self.trip_label.config(text=f"本次: {self.vehicle.trip_distance:.1f} km")
        
        # 更新状态
        if self.vehicle.current_speed == 0:
            status = "状态: 停车"
        elif self.vehicle.current_speed == self.vehicle.target_speed:
            status = f"状态: 匀速 {self.vehicle.current_speed:.0f} km/h"
        elif self.vehicle.current_speed < self.vehicle.target_speed:
            status = f"状态: 加速至 {self.vehicle.target_speed:.0f} km/h"
        else:
            status = f"状态: 减速至 {self.vehicle.target_speed:.0f} km/h"
        
        # 添加警告
        warnings = []
        if self.vehicle.fuel_level < 10:
            warnings.append("燃油不足")
        if self.vehicle.engine_temp > 100:
            warnings.append("水温过高")
        
        if warnings:
            status += " ⚠️ " + " | ".join(warnings)
        
        self.status_label.config(text=status)
    
    def simulate_driving(self):
        """模拟自动驾驶"""
        # 5%概率改变目标速度
        if random.randint(1, 200) == 1:
            self.vehicle.target_speed = random.randint(0, config.MAX_SPEED)
    
    def start_update_thread(self):
        """启动更新线程"""
        def update_loop():
            while self.vehicle.is_running:
                try:
                    # 更新数据
                    self.vehicle.update()
                    
                    # 模拟驾驶
                    self.simulate_driving()
                    
                    # 更新界面（需要在主线程中执行）
                    self.root.after(0, self.update_display)
                    
                    time.sleep(config.UPDATE_INTERVAL)
                    
                except Exception as e:
                    print(f"更新线程错误: {e}")
                    break
        
        update_thread = threading.Thread(target=update_loop, daemon=True)
        update_thread.start()
    
    def on_closing(self):
        """窗口关闭事件"""
        self.vehicle.is_running = False
        self.root.destroy()
    
    def run(self):
        """运行应用"""
        print("🚗 启动Python+Tkinter汽车仪表盘...")
        
        # 设置关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
        
        try:
            # 启动GUI事件循环
            self.root.mainloop()
        except KeyboardInterrupt:
            print("\n👋 程序退出")
        finally:
            self.vehicle.is_running = False

def main():
    """主函数"""
    print("═══════════════════════════════════════")
    print("🐍 Python+Tkinter 汽车仪表盘")
    print("═══════════════════════════════════════")
    print("使用内置Tkinter库，无需额外依赖")
    print("支持编译为独立exe文件")
    print("═══════════════════════════════════════")
    
    try:
        # 创建并运行仪表盘
        dashboard = Dashboard()
        dashboard.run()
        
    except Exception as e:
        print(f"❌ 程序运行错误: {e}")
        import traceback
        traceback.print_exc()
        input("按Enter键退出...")
        return 1
    
    return 0

if __name__ == "__main__":
    sys.exit(main())